package wifiadm

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/shopspring/decimal"
	"log"
	"sort"
	"strconv"
	"strings"
	"time"

	"yundian/internel/app/dao"
	"yundian/internel/app/helper"
	"yundian/internel/app/helper/request"
	"yundian/internel/app/logic"
	"yundian/internel/app/models/devploys"
	"yundian/internel/app/models/devrule"
	"yundian/internel/app/models/orders"
	"yundian/internel/app/models/ordersstatistics"
	"yundian/internel/app/models/placemodel/placeoperatelog"
	"yundian/internel/app/models/placemodel/places"
	"yundian/internel/app/models/placesinformationconfig"
	"yundian/internel/app/models/ploys"
	"yundian/internel/app/models/prices"
	"yundian/internel/app/models/priceslog"
	"yundian/internel/app/models/users"
	"yundian/internel/pkg/dingo"
	. "yundian/internel/pkg/dingo/result"
	"yundian/internel/pkg/utils"
)

// ------- 网点相关API请求处理 placeHandler -------

// HandleGetBrandConfigList 查询品牌列表
func HandleGetBrandConfigList(ctx *gin.Context) {
	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前登录用户ID
	dingo.ErrorIf(err).Unwrap()

	param := &request.GetBrandConfigListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.LoginUserId = loginUserId
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)
	param.ParentId, _ = helper.GetParentIdFromCtx(ctx)

	data := dao.NewPlaceDao().GetBrandConfigList(param)
	lists := data.Unwrap().([]*request.GetBrandConfigListRes)

	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  0,
		Data:       lists,
	})(OK)
}

// HandleGetBrandRelevancyConfigList 门店关联品牌配置
func HandleGetBrandRelevancyConfigList(ctx *gin.Context) {
	loginUserId, err := helper.GetUserIdFromCtx(ctx)
	dingo.ErrorIf(err).Unwrap()

	param := &request.GetBrandRelevancyConfigListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.LoginUserId = loginUserId
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)
	param.ParentId, _ = helper.GetParentIdFromCtx(ctx)

	data := dao.NewPlaceDao().GetBrandRelevancyConfigList(param)
	lists := data.Unwrap().([]*request.GetBrandRelevancyConfigListRes)

	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		Data:       lists,
	})(OK)
}

func HandleInsertBrandRelevancyConfig(ctx *gin.Context) {
	param := &placemodel.PlaceBrandRelevancyConfigDb{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	data := dao.NewPlaceDao().InsertBrandRelevancyConfig(param)
	Response(ctx)("", CodeSuccess, data.Err == nil)(OK)
}

func HandleUpdateBrandRelevancyConfig(ctx *gin.Context) {
	param := &placemodel.PlaceBrandRelevancyConfigDb{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	data := dao.NewPlaceDao().UpdateBrandRelevancyConfig(param)
	Response(ctx)("", CodeSuccess, data.Err == nil)(OK)
}

func HandleDeleteBrandRelevancyConfig(ctx *gin.Context) {
	param := &placemodel.PlaceBrandRelevancyConfigDb{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	data := dao.NewPlaceDao().DeleteBrandRelevancyConfig(param)
	Response(ctx)("", CodeSuccess, data.Err == nil)(OK)
}

func GetStewardPlaceInformationConfig(ctx *gin.Context) {
	loginUserId, err := helper.GetUserIdFromCtx(ctx)
	dingo.ErrorIf(err).Unwrap()

	param := &request.StewardPlaceInformationConfigReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.LoginUserId = loginUserId

	data := dao.NewPlaceDao().GetStewardInformationConfig([]int{param.PlaceId})
	Response(ctx)("", CodeSuccess, data.Unwrap())(OK)
}

func SetStewardPlaceInformationConfig(ctx *gin.Context) {
	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前登录用户ID
	dingo.ErrorIf(err).Unwrap()

	param := &request.StewardPlaceInformationConfigReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.LoginUserId = loginUserId

	if data := dao.NewPlaceDao().SetStewardPlaceInformationConfig(param); data.Err != nil {
		Response(ctx)("", CodeInternalServerError, false)(OK)
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

// SetStewardPlace 设置网点
func SetStewardPlace(ctx *gin.Context) {
	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前登录用户ID
	dingo.ErrorIf(err).Unwrap()

	param := &request.SetStewardPlaceReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.LoginUserId = loginUserId

	if data := dao.NewPlaceDao().SetStewardPlace(param); data.Err != nil {
		Response(ctx)("", CodeInternalServerError, false)(OK)
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func HandlerGetStewardSearchPlaceList(ctx *gin.Context) {
	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前登录用户ID
	dingo.ErrorIf(err).Unwrap()

	param := &request.GetStewardPlaceListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.LoginUserId = loginUserId
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)

	data := dao.NewPlaceDao().GetStewardSearchPlaceList(param)
	lists := data.Unwrap().([]*request.GetStewardSearchPlaceListRes)

	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  0,
		Data:       lists,
	})(OK)
}

// GetStewardPlaceList 查询网点
func GetStewardPlaceList(ctx *gin.Context) {
	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前登录用户ID
	dingo.ErrorIf(err).Unwrap()

	param := &request.GetStewardPlaceListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.LoginUserId = loginUserId
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)
	param.ParentId, _ = helper.GetParentIdFromCtx(ctx)

	data := dao.NewPlaceDao().GetStewardPlaceList(param)
	lists := data.Unwrap().([]*request.GetStewardPlaceListRes)

	var placeIds []int
	for _, item := range lists {
		placeIds = append(placeIds, item.Id)
	}
	picList := dao.NewPlaceDao().GetStewardInformationConfig(placeIds).Unwrap().([]*placemodel.PlacesInformationConfig)
	for _, item := range lists {
		for _, item1 := range picList {
			if item.Id == item1.PlaceId && item1.Status == 1 {
				item.InformationType = item1.Type
				break
			}
		}
	}

	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  0,
		Data:       lists,
	})(OK)
}

func HandleGetPlaceAwaitingModerationList(ctx *gin.Context) {
	isAdmin, err := helper.GetIsAdminFromCtx(ctx)
	dingo.ErrorIf(err).Unwrap()
	if isAdmin != helper.TypeNumIsAdminOperator && isAdmin != helper.TypeNumIsAdminAdministrator && isAdmin != helper.TypeNumIsAdminStaff {
		Response(ctx)("", CodeInvalidParam, nil)
		return
	}

	param := &request.PlacesListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	data := dao.NewPlaceDao().GetPlaceAwaitingModerationList(param)
	list := data.Unwrap().([]*request.GetPlaceAwaitingModerationListRes)

	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       list,
	})(OK)
}

// HandleSetPlaceAwaitingModerationStatus 2.0门店审核操作
func HandleSetPlaceAwaitingModerationStatus(ctx *gin.Context) {
	userId, err := helper.GetUserIdFromCtx(ctx)
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	userName, _ := helper.GetUserNameFromCtx(ctx)

	//isAdmin, err := helper.GetIsAdminFromCtx(ctx)
	//dingo.ErrorIf(err).Unwrap()
	//if isAdmin != helper.TypeNumIsAdminOperator && isAdmin != helper.TypeNumIsAdminAdministrator {
	//	Response(ctx)("", CodeInvalidParam, nil)
	//	return
	//}

	param := &request.SetPlaceAwaitingModerationStatusReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	if data := dao.NewPlaceDao().SetPlaceAwaitingModerationStatus(param); data.Err != nil {
		Response(ctx)("", CodeInternalServerError, nil)
		return
	}

	// 门店店审核写入日志
	pInfo := dao.NewPlaceDao().GetPlaceDetailById(param.PlaceId).Unwrap().(*placemodel.PlaceModel)
	var remark string
	if param.Status == helper.TypeNumPlaceStatusYes {
		remark = "审核通过"
	} else if param.Status == helper.TypeNumPlaceStatusNoReview {
		remark = "审核失败"
	} else {
		remark = "门店审核"
	}
	pol := placemodel.PlaceOperateLog{
		PlaceId:           pInfo.Id,
		PlaceName:         pInfo.PlaceName,
		OperationUserId:   userId,
		OperationUserName: userName,
		OperateIP:         ctx.ClientIP(),
		Description:       "门店审核",
		Remark:            remark,
		CreateAt:          0,
		BeforeField:       "",
		AfterField:        "",
	}
	p := &request.PlaceInsertReq{
		UserId:       pInfo.UserID,
		BranchUserId: pInfo.BranchUserId,
		PlaceName:    pInfo.PlaceName,
		ClassName:    pInfo.ClassName,
		Province:     pInfo.Province,
		City:         pInfo.City,
		County:       pInfo.County,
		Address:      pInfo.Address,
		Status:       uint8(pInfo.Status),
		PlaceDesc:    pInfo.PlaceDesc,
		MaintainerId: pInfo.MaintainerId,
		RegionIds:    pInfo.RegionIds,
		EntryMoney:   pInfo.EntryMoney,
		EntryAt:      int64(pInfo.EntryAt),
		HotelId:      pInfo.HotelId,
		KaUserId:     pInfo.KaUserId,
		ProvinceId:   pInfo.ProvinceId,
		CityId:       pInfo.CityId,
		CountyId:     pInfo.CountyId,
		AreaId:       pInfo.AreaId,
		IsAd:         pInfo.IsAd,
		IsBusiness:   pInfo.IsBusiness,
		ProjectLabel: pInfo.ProjectLabel,
		PlaceLicense: pInfo.PlaceLicense,
		PlaceFace:    pInfo.PlaceFace,
		PlaceDesign:  pInfo.PlaceDesign,
	}

	dingo.Task(logic.NewLogsLogic().InsertPlaceOperateLogLogic, func() {}, pol, p, pInfo)

	Response(ctx)("", CodeSuccess, true)(OK)
}

// HandleGetAllPlaceList 获取所有门店列表
func HandleGetAllPlaceList(ctx *gin.Context) {
	param := &request.PlacesListReq{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	data := dao.NewPlaceDao().GetAllPlaceList(param)
	lists := data.Unwrap().([]*placeresp.PlaceListByAll)

	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       lists,
	})(OK)
}

// GetPlaceList 获取网点列表API
func HandleGetPlaceList(ctx *gin.Context) {
	param := &request.PlacesListReq{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前代理商ID
	isAdmin, err := helper.GetIsAdminFromCtx(ctx)
	parentId, err := helper.GetParentIdFromCtx(ctx)
	dingo.ErrorIf(err).Unwrap()

	// 超级管理员 && 运营商下的员工
	if helper.IsAdminAndStaff(isAdmin, parentId) {
		loginUserId = 2
	}
	//log.Println(isAdmin, parentId, loginUserId)
	data := dao.NewPlaceDao().GetPlaceList(param, loginUserId)
	lists := data.Unwrap().([]*placeresp.PlaceList)

	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       lists,
	})(OK)
}

// 网点下载
//func HandleGetPlaceDownload(ctx *gin.Context) {
//	param := &request.PlacesListReq{}
//	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()
//
//	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前代理商ID
//	if err != nil {
//		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
//		return
//	}
//	//isAdmin, err := helper.GetIsAdminFromCtx(ctx) // 从上下文中获取用户是否为管理员
//	//if err != nil {
//	//	Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
//	//	return
//	//}
//	//
//	//isPlace, err := helper.GetIsPlaceFromCtx(ctx)
//	//data := dao.NewPlaceDao().GetPlaceList(param, loginUserId, isAdmin, isPlace)
//	data := dao.NewPlaceDao().GetPlaceList(param, loginUserId)
//	lists := data.Unwrap().([]*placeresp.GetPlaceIdWithHotelId)
//
//	var placeIds []int
//	for _, lst := range lists {
//		// 计算当前商户的总收益
//		//dividendsMoney := dao.NewOrderDao().GetUserIncome(lst.UserID).Unwrap().(int64)
//		// 提现
//		//cashMoney := dao.NewOrderDao().GetCashLogByUserId(lst.UserID).Unwrap().(int64)
//		//lst.Income = decimal.NewFromInt(dividendsMoney).Sub(decimal.NewFromInt(cashMoney)).Div(decimal.NewFromInt(100)).StringFixed(2)
//
//		//count := dao.NewDeviceDao().GetDeviceCountByPlaceId(lst.Id).Unwrap().(int64)
//		//lst.DeviceCount = int(count)
//		placeIds = append(placeIds, lst.Id)
//
//		// 计算当前商户的设备条数
//		//lst.DevCount = dao.NewDeviceDao().GetDeviceCountGroupByDeviceTypeId(lst.Id).Unwrap().([]placeresp.PlaceDeviceCount)
//	}
//
//	countList := dao.NewDeviceDao().GetDeviceCountByPlaceIds(placeIds).Unwrap().([]placeresp.PlaceDeviceCount)
//	for _, item := range countList {
//		for _, lst := range lists {
//			if lst.Id == item.PlaceId {
//				lst.DeviceCount = item.Total
//				break
//			}
//		}
//	}
//
//	Response(ctx)("", CodeSuccess, ResponseList{
//		PageNo:     param.PageNo,
//		PageSize:   param.PageSize,
//		TotalCount: data.Val().(int64),
//		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
//		Data:       lists,
//	})(OK)
//}

// HandlePlaceDetail 获取商户详情
func HandlePlaceDetail(ctx *gin.Context) {
	param := &struct {
		PlaceId int `form:"id"`
		Limit   int `form:"limit"`
		Offset  int `form:"offset"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	placeInfo := dao.NewPlaceDao().GetPlaceUserInfo(param.PlaceId).Unwrap().(*placeresp.PlaceInfo)
	dMoney := dao.NewOrderDao().GetDividendsMoneyByUserId(placeInfo.UserID).Unwrap().(int64) // 累计收益
	cMoney := dao.NewOrderDao().GetCashLogByUserId(placeInfo.UserID).Unwrap().(int64)        // 提现金额
	placeInfo.DividMoney = decimal.NewFromInt(dMoney).Div(decimal.NewFromInt(100)).StringFixed(2)
	placeInfo.CashMoney = decimal.NewFromInt(cMoney).Div(decimal.NewFromInt(100)).StringFixed(2)
	placeInfo.Money = decimal.NewFromInt(dMoney).Sub(decimal.NewFromInt(cMoney)).Div(decimal.NewFromInt(100)).StringFixed(2)
	placeInfo.PlaceDeviceCount = dao.NewDeviceDao().GetDeviceCountGroupByProdType(param.PlaceId).Unwrap().([]placeresp.PlaceDeviceCount)
	placeInfo.OrderList = dao.NewOrderDao().
		GetOrderListByPlaceId(param.Limit, param.Offset, param.PlaceId).
		Unwrap().([]orders.OrderModel)
	//placeInfo.OrderCount = dao.NewOrderDao().GetOrderListByPlaceId(param.PlaceId).Val().(int64)
	Response(ctx)("", CodeSuccess, placeInfo)(OK)
}

// InsertPlace 新增网点信息API
func HandleInsertPlace(ctx *gin.Context) {
	userId, err := helper.GetUserIdFromCtx(ctx)
	dingo.ErrorIf(err).Unwrap()
	userName, _ := helper.GetUserNameFromCtx(ctx)

	param := &request.PlaceInsertReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	//查询网点名称是否重复
	_, isRepeat := dao.NewPlaceDao().GetPlaceNameIsRepeat(param.PlaceName)
	if isRepeat > 0 {
		Response(ctx)("该网点名称已被使用", CodeError, false)(OK)
		return
	}

	placeInfo := dao.NewUserDao().InsertPlaceInfo(param).Unwrap().(*placemodel.PlaceModel)

	ruleInfos := dao.NewPricesDao().GetDeviceRuleInfoList().Unwrap().([]devrule.DeviceRulesModel)

	//查询商户奖励规则
	ploysInfo := dao.NewPricesDao().GetDevicePloysInfoList().Unwrap().([]devploys.DevicePloysModel)

	// 新增商户计费规则
	for _, ruleInfo := range ruleInfos {
		m := prices.New()
		m.DeviceTypeId = ruleInfo.TypeId
		m.PlaceId = placeInfo.Id
		m.Status = ruleInfo.Status
		m.ProductId = utils.Str2Md5(helper.GenerateUUID())

		// -----套餐模式 开始------
		m.UseDuration = ruleInfo.UseDuration // 使用时长
		m.PayMoney = ruleInfo.PayMoney       // 支付金额-单位分
		m.SetMealNum = ruleInfo.SetMealNum   // 规则序号
		m.RuleName = ruleInfo.RuleName       // 规则名
		m.IsRecommend = ruleInfo.IsRecommend // 是否推荐
		m.Priority = ruleInfo.Priority       // 排序
		// -----套餐模式 结束------

		// -----计时模式 开始------
		m.MaxPayPrice = ruleInfo.MaxPayPrice           // 日封顶价格
		m.PayIntervalPrice = ruleInfo.PayIntervalPrice // 每60分钟支付2元
		m.PayInterval = int(ruleInfo.PayInterval)      // 每60分钟支付2元
		m.MaxTime = ruleInfo.MaxTime                   // 最大使用时长
		m.BasePrice = ruleInfo.BasePrice               // 最低使用价格
		m.BaseTimes = int(ruleInfo.BaseTimes)          // 最低使用时长
		m.FreeTimes = int(ruleInfo.FreeTimes)          // 免费使用时长
		m.Deposit = ruleInfo.Deposit                   //  押金
		// -----计时模式 结束------
		//酒店ID

		m.CreateAt = dingo.Time(time.Now().Unix())
		dao.NewPricesDao().InsertPlacePrice(m).Unwrap() // 新增 商户价格
	}

	//新增商户奖励规则
	for _, ploysVal := range ploysInfo {
		m := ploys.New()
		m.PlaceId = placeInfo.Id
		m.PlaceName = placeInfo.PlaceName

		//
		m.Status = ploysVal.Status
		m.UserId = ploysVal.UserId
		m.Type = ploysVal.Type
		m.TypeId = ploysVal.TypeId
		m.UserName = ploysVal.UserName
		m.Num = ploysVal.Num
		m.Range = ploysVal.Range
		m.PloyType = ploysVal.PloyType
		m.PloyName = ploysVal.PlaceName
		m.SharedMode = ploysVal.SharedMode

		m.CreateAt = dingo.Time(time.Now().Unix())

		dao.NewPricesDao().InsertPloys(m).Unwrap() // 新增商户奖励规则
	}

	// 门店新增写入日志
	pol := placemodel.PlaceOperateLog{
		PlaceId:           placeInfo.Id,
		PlaceName:         placeInfo.PlaceName,
		OperationUserId:   userId,
		OperationUserName: userName,
		OperateIP:         ctx.ClientIP(),
		Description:       "门店新增",
		Remark:            "门店新增",
		CreateAt:          0,
		BeforeField:       "",
		AfterField:        "",
		PlaceDesc:         param.PlaceDesc,
		PlaceDescAfter:    param.PlaceDesc,
	}
	dingo.Task(logic.NewLogsLogic().InsertPlaceOperateLogLogic, func() {}, pol, param, placeInfo)

	if placeInfo.Status == 4 { // 需要审核的门店
		dingo.Task(logic.NewShWxNotificationsLogic().WeChatGroupRobotNotificationsByPlace,
			func() {}, placeInfo.Id)
	}

	Response(ctx)("", CodeInsertSuccess, placeInfo)(OK)
}

func HandleInsertPlaceImg(ctx *gin.Context) {
	param := &request.PlaceInsertReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	placeInfo := dao.NewUserDao().UpdatePlaceInfoImg(param).Unwrap().(*placemodel.PlaceModel)

	Response(ctx)("", CodeInsertSuccess, placeInfo)(OK)
}

// UpdatePlace 更新网点信息API
func HandleUpdatePlace(ctx *gin.Context) {
	userId, err := helper.GetUserIdFromCtx(ctx)
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	userName, _ := helper.GetUserNameFromCtx(ctx)
	isAdmin, _ := helper.GetIsAdminFromCtx(ctx)
	parentId, _ := helper.GetParentIdFromCtx(ctx)

	t := 0
	// 运营商 || 超级管理员 || 运营商下的员工
	if helper.IsAdminAndStaff(isAdmin, parentId) {
		t = 1
	}

	param := &request.PlaceInsertReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	//查询网点名称是否重复
	placeModel, isRepeat := dao.NewPlaceDao().GetPlaceNameIsRepeat(param.PlaceName)
	isRepeatModel := placeModel.Unwrap().(*placemodel.PlaceModel)
	if isRepeat > 0 && param.Id != isRepeatModel.Id {
		Response(ctx)("该网点名称已被使用", CodeError, false)(OK)
		return
	}

	// 门店修改写入日志
	pInfo := dao.NewPlaceDao().GetPlaceDetailById(param.Id).Unwrap().(*placemodel.PlaceModel)
	pol := placemodel.PlaceOperateLog{
		PlaceId:           pInfo.Id,
		PlaceName:         pInfo.PlaceName,
		OperationUserId:   userId,
		OperationUserName: userName,
		OperateIP:         ctx.ClientIP(),
		Description:       "门店修改",
		Remark:            "门店修改",
		CreateAt:          0,
		BeforeField:       "",
		AfterField:        "",
		PlaceDesc:         pInfo.PlaceDesc,
		PlaceDescAfter:    param.PlaceDesc, // 修改之后
	}

	dingo.Task(logic.NewLogsLogic().InsertPlaceOperateLogLogic, func() {}, pol, param, pInfo)

	Response(ctx)("", CodeUpdateSuccess,
		dao.NewUserDao().UpdatePlaceInfo(param, t).Unwrap())(OK)
}

// DeletePlaceById 删除网点信息API
func HandleDeletePlace(ctx *gin.Context) {
	userId, err := helper.GetUserIdFromCtx(ctx)
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	userName, _ := helper.GetUserNameFromCtx(ctx)
	param := &struct {
		Id     int    `json:"id" binding:"required,gt=0"`
		Income string `json:"income"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	// 判断商户是否绑定了设备
	total := dao.NewDeviceDao().GetDeviceCountByPlaceId(param.Id).Unwrap().(int64)
	if total > 0 {
		Response(ctx)("删除失败，请先解绑设备", CodeSuccess, false)(OK)
		return
	}
	pInfo := dao.NewPlaceDao().GetPlaceDetailById(param.Id).Unwrap().(*placemodel.PlaceModel)
	isDelete := dao.NewPlaceDao().DeletePlaceById(param.Id).Unwrap().(bool)
	if isDelete {
		pol := placemodel.PlaceOperateLog{
			PlaceId:           pInfo.Id,
			PlaceName:         pInfo.PlaceName,
			OperationUserId:   userId,
			OperationUserName: userName,
			OperateIP:         ctx.ClientIP(),
			Description:       "门店删除",
			Remark:            "门店删除",
			CreateAt:          0,
			BeforeField:       "",
			AfterField:        "",
		}
		p := &request.PlaceInsertReq{}
		p.UserId = pInfo.UserID
		p.BranchUserId = pInfo.BranchUserId
		p.PlaceName = pInfo.PlaceName
		dingo.Task(logic.NewLogsLogic().InsertPlaceOperateLogLogic, func() {}, pol, p, pInfo)
		Response(ctx)("删除成功", CodeSuccess, true)(OK)
		return
	} else {
		Response(ctx)("删除失败", CodeError, false)(OK)
		return
	}
}

// HandleSavePlaceProfit 修改网点分成比例
func HandleSavePlaceProfit(ctx *gin.Context) {
	param := &struct {
		UserId int `json:"userId"`
		Pcl    int `json:"profitProportion"`
		Sm     int `json:"smProfitProportion"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	log.Println(param)

	Response(ctx)("修改成功", CodeSuccess,
		dao.NewUserDao().UpdatePlaceProfit(param.UserId, param.Pcl, param.Sm).Unwrap())(OK)
}

func HandleSaveDraw(ctx *gin.Context) {
	param := &struct {
		PlaceId int    `json:"placeId"`
		DrawStr string `json:"drawStr"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	Response(ctx)("修改成功", CodeSuccess,
		dao.NewUserDao().UpdatePlaceDrawStr(param.PlaceId, param.DrawStr).Unwrap())(OK)
}

// 按用户搜索，批量修改下级的抽单
func HandleSaveDrawByLevel(ctx *gin.Context) {
	param := &struct {
		AgentUserId int    `json:"agentUserId"`
		DrawStr     string `json:"drawStr"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	var placeIds []int
	//查询门店
	//placesBranchIds := dao.NewUserDao().GetPlacesId(userId).Unwrap().([]int) // 查询 分公司下所有门店
	//userIds := dao.NewUserDao().QueryChildUserIds(userId).Unwrap().([]int)
	//获取直属或下级网点Id
	userIdArr := dao.NewUserDao().QueryChildUserIds(param.AgentUserId).Unwrap().([]int)
	placeIdArr := dao.NewPlaceDao().GetPlaceByIds(userIdArr).Unwrap().([]int)

	//合并网点
	placeIds = append(placeIds, placeIdArr...)

	//去重网点
	placesIds := utils.RemoveRepByMap(placeIds)

	for _, id := range placesIds {
		dao.NewUserDao().UpdatePlaceDrawStr(id, param.DrawStr).Unwrap()
	}

	Response(ctx)("修改成功", CodeSuccess, true)(OK)
}

// 按用户搜索，批量修改下级的抽单
func HandleSaveDrawByUserId(ctx *gin.Context) {
	param := &struct {
		AgentUserId int `json:"agentUserId"`
		Range       int `gorm:"column:range" json:"range"`
		Num         int `gorm:"column:num" json:"num"`
		Type        int `gorm:"column:type" json:"type"`
		Status      int `gorm:"column:status" json:"status"`

		TypeId     int    `gorm:"column:type_id" json:"typeId"`
		SharedMode string `gorm:"column:shared_mode" json:"sharedMode"`
		PloyType   int    `gorm:"column:ploy_type" json:"ployType"`
		PloyName   string `gorm:"column:ploy_name" json:"ployName"`

		PlaceId   int    `gorm:"column:place_id" json:"placeId"`     // 网点ID
		PlaceName string `gorm:"column:place_name" json:"placeName"` // 网点名
		UserId    int    `gorm:"column:user_id" json:"userId"`       // 代理商ID
		UserName  string `gorm:"column:user_name" json:"userName"`

		Name string `gorm:"column:name" json:"name"` //奖励规则名称

		CreateAt dingo.Time `gorm:"column:create_at" json:"createAt"`
		UpdateAt dingo.Time `gorm:"column:update_at" json:"updateAt"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	var placeIds []int
	//查询门店
	//placesBranchIds := dao.NewUserDao().GetPlacesId(userId).Unwrap().([]int) // 查询 分公司下所有门店
	//userIds := dao.NewUserDao().QueryChildUserIds(userId).Unwrap().([]int)
	//获取直属或下级网点Id
	userIdArr := dao.NewUserDao().QueryChildUserIds(param.AgentUserId).Unwrap().([]int)
	placeIdArr := dao.NewPlaceDao().GetPlaceByIds(userIdArr).Unwrap().([]int)

	//合并网点
	placeIds = append(placeIds, placeIdArr...)

	//去重网点
	placesIds := utils.RemoveRepByMap(placeIds)

	param.UpdateAt = dingo.Time(time.Now().Unix())
	if param.Num > param.Range || param.Num > 5 {
		Response(ctx)("修改失败,抽单数不能超过5", CodeError, "修改失败,抽单数不能超过5")(OK)
		return
	}

	m := ploys.New()
	m.Range = param.Range
	m.Num = param.Num
	m.UserName = param.UserName
	m.PloyType = param.PloyType
	m.PloyName = param.PloyName
	m.Status = param.Status
	m.SharedMode = param.SharedMode
	m.Type = param.Type
	m.PloyType = param.PloyType
	m.UpdateAt = dingo.Time(time.Now().Unix())
	for _, id := range placesIds {
		m.PlaceId = id
		dao.NewPloysDao().SavePlacePloyByPlaceId(m).Unwrap()
	}

	Response(ctx)("修改成功", CodeSuccess, true)(OK)
}

// HandleUpdatePlaceMeiTuan 更新网点美团信息
func HandleUpdatePlaceMeiTuan(ctx *gin.Context) {
	param := &struct {
		Id      int    `json:"id"` // ID
		Url     string `json:"url"`
		Banners string `json:"banners"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	Response(ctx)("", CodeUpdateSuccess,
		dao.NewUserDao().UpdatePlaceMeiuan(param.Id, param.Url, param.Banners).Unwrap())(OK)
}

// 获取商户价格信息
func HandleGetPlacePrice(ctx *gin.Context) {
	param := &struct {
		PlaceId int `form:"placeId"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     1,
		PageSize:   10,
		TotalCount: 0,
		TotalPage:  0,
		Data:       dao.NewPricesDao().GetPlacePriceList(param.PlaceId).Unwrap(),
	})(OK)
	//Response(ctx)("", CodeSuccess,
	//	dao.NewPricesDao().GetPlacePriceList(param.PlaceId).Unwrap())(OK)
}

// 获取商户价格
func HandleGetPriceList(ctx *gin.Context) {
	param := &struct {
		PlaceId      int `form:"placeId"`
		DeviceTypeId int `form:"deviceTypeId"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	Response(ctx)("", CodeSuccess,
		dao.NewPricesDao().GetPlacePriceByTypeId(param.PlaceId, param.DeviceTypeId, 5, 0, "create_at desc, priority asc").Unwrap())(OK)
}

// 保存商户价格配置
func HandleSavePlacePrice(ctx *gin.Context) {
	param := prices.New()
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.ProductId = utils.Str2Md5(helper.GenerateUUID())
	param.Status = 1
	param.CreateAt = dingo.Time(time.Now().Unix())

	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前代理商ID
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	loginUserName, err1 := helper.GetUserNameFromCtx(ctx) // 获取当前代理商ID
	if err1 != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}

	// 添加日志
	limit := 1
	beforeInfo := ""
	if param.DeviceTypeId == 12 {
		limit = 5
	} // 多套餐密码线
	// 免押密码线计费
	priceInfo := dao.NewPricesDao().GetPlacePriceByTypeIdPre(param.PlaceId, param.DeviceTypeId, limit, 0, "create_at desc, priority asc").Unwrap().([]*prices.PriceModel)
	for _, lst := range priceInfo {
		// 修改前的 免押密码线计费规则
		beforeInfo = GetPlacePriceChangeInfo(lst, "修改之前，")
	}
	// 修改后的 免押密码线计费规则
	afterInfo := GetPlacePriceChangeInfo(param, "修改之后，")

	// 初始化模型
	priceslogModel := priceslog.New()
	priceslogModel.UserId = loginUserId
	priceslogModel.UserName = loginUserName
	priceslogModel.PlaceId = param.PlaceId
	priceslogModel.CreateAt = dingo.Time(time.Now().Unix())
	priceslogModel.PriceBefore = beforeInfo
	priceslogModel.PriceAfter = afterInfo
	priceslogModel.OperateIP = ctx.ClientIP()

	dao.NewPlacePriceLogsDao().InsertPlacePriceLogs(priceslogModel)

	Response(ctx)("修改成功", CodeSuccess, dao.NewPricesDao().SavePlacePrice(param).Unwrap())(OK)
}

// 获取价格修改详细
func GetPlacePriceChangeInfo(lst *prices.PriceModel, pricesInfo string) string {
	// 免押密码线
	if lst.DeviceTypeId == 10 {
		// 押金
		depositStr := strconv.FormatInt(lst.Deposit/100, 10)
		// 最少使用
		baseTimesStr := strconv.Itoa(lst.BaseTimes)
		// 最低使用费用
		basePriceStr := strconv.FormatInt(lst.BasePrice/100, 10)
		// 每使用
		payIntervalStr := strconv.Itoa(lst.PayInterval)
		// 费用
		payIntervalPriceStr := strconv.FormatInt(lst.PayIntervalPrice/100, 10)
		// 免费使用时长
		freeTimesStr := strconv.Itoa(lst.FreeTimes)
		// 日封顶
		maxPayPriceStr := strconv.FormatInt(lst.MaxPayPrice/100, 10)
		// 最大使用时长
		maxTimeStr := strconv.Itoa(lst.MaxTime)

		pricesInfo = pricesInfo + "免押密码线计费规则为 [押金：" + depositStr + "元，最少使用：" + baseTimesStr + "分钟，最低使用费用：" + basePriceStr + "元，每使用：" + payIntervalStr +
			"分钟，费用：" + payIntervalPriceStr + "元，免费使用时长：" + freeTimesStr + "分钟，日封顶：" + maxPayPriceStr + "元，最大使用时长：" + maxTimeStr + "分钟]"

	} else if lst.DeviceTypeId == 12 { // 套餐密码线

		// 套餐名称

		// 使用时长
		useDurationStr := strconv.Itoa(lst.UseDuration)
		// 支付金额
		payMoneyStr := strconv.FormatInt(lst.PayMoney/100, 10)
		// 是否显示
		pricesInfo = pricesInfo + "[套餐名称：" + lst.RuleName + "，使用时长：" + useDurationStr + "，支付金额：" + payMoneyStr + "，是否显示："

		pricesInfo = fmt.Sprint(pricesInfo, lst.Status, "]，")
	}

	return pricesInfo
}

// 获取商户奖励规则
func HandleGetPlacePloy(ctx *gin.Context) {
	param := &struct {
		PlaceId    int    `form:"id"`
		SharedMode string `form:"sharedMode"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	Response(ctx)("", CodeSuccess, dao.NewPloysDao().GetPlacePloyInfo(param.PlaceId, param.SharedMode).Unwrap())(OK)
}

// 获取商户奖励规则
func HandleGetPlacePloyInfo(ctx *gin.Context) {
	param := &struct {
		PlaceId    int    `form:"placeId"`
		SharedMode string `form:"sharedMode"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	Response(ctx)("", CodeSuccess,
		dao.NewPloysDao().GetPlacePloyInfoByPaceIdAndMode(param.PlaceId, param.SharedMode).Unwrap())(OK)
}

// 保存商户奖励规则配置
func HandleSavePlacePloy(ctx *gin.Context) {
	param := ploys.New()
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.UpdateAt = dingo.Time(time.Now().Unix())
	if param.Num > param.Range || param.Num > 5 {
		Response(ctx)("修改失败,抽单数不能超过5", CodeError, "修改失败,抽单数不能超过5")(OK)
		return
	}
	placeInfo := dao.NewPlaceDao().GetPlaceById(param.PlaceId).Unwrap().(*placemodel.PlaceModel)
	if placeInfo.ProjectLabel == "hotel_xc" && param.Num > 3 {
		Response(ctx)("修改失败,携程项目抽单数不能超过3", CodeError, "修改失败,携程项目抽单数不能超过3")(OK)
		return
	}

	Response(ctx)("修改成功", CodeSuccess, dao.NewPloysDao().SavePlacePloys(param).Unwrap())(OK)
}

func HandleSavePlacePloyByPlaceId(ctx *gin.Context) {
	param := ploys.New()
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.UpdateAt = dingo.Time(time.Now().Unix())
	if param.Num > param.Range || param.Num > 5 {
		Response(ctx)("修改失败,抽单数不能超过5", CodeError, "修改失败,抽单数不能超过5")(OK)
		return
	}
	placeInfo := dao.NewPlaceDao().GetPlaceById(param.PlaceId).Unwrap().(*placemodel.PlaceModel)
	if placeInfo.ProjectLabel == "hotel_xc" && param.Num > 3 {
		Response(ctx)("修改失败,携程项目抽单数不能超过3", CodeError, "修改失败,携程项目抽单数不能超过3")(OK)
		return
	}

	Response(ctx)("修改成功", CodeSuccess, dao.NewPloysDao().SavePlacePloyByPlaceId(param).Unwrap())(OK)
}

func HandleBatchSavePlacePloy(ctx *gin.Context) {
	var placesIds []int
	param := &request.SavePloyReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	// 抽单数验证
	if param.Num > param.Range || param.Num > 5 {
		Response(ctx)("修改失败,抽单数不能超过5", CodeError, "修改失败,抽单数不能超过5")(OK)
		return
	}

	// 按用户下级更新抽单规则
	if param.AgentUserId > 0 {
		var placeIds []int
		//获取直属或下级网点Id
		userIdArr := dao.NewUserDao().QueryChildUserIds(param.AgentUserId).Unwrap().([]int)
		placeIdArr := dao.NewPlaceDao().GetPlaceByIds(userIdArr).Unwrap().([]int)
		placeIds = append(placeIds, placeIdArr...) //合并网点
		placesIds = utils.RemoveRepByMap(placeIds) //去重网点
	}

	// 批量修改商户Id
	if len(param.PlaceIds) > 0 {
		placesIds = param.PlaceIds
	}

	m := ploys.New()
	m.Range = param.Range
	m.Num = param.Num
	m.PloyType = param.PloyType
	m.PloyName = param.PloyName
	m.Status = param.Status
	m.SharedMode = param.SharedMode
	m.UpdateAt = dingo.Time(time.Now().Unix())
	for _, id := range placesIds {
		m.PlaceId = id
		dao.NewPloysDao().SavePlacePloyByPlaceId(m).Unwrap()
	}

	Response(ctx)("修改成功", CodeSuccess, true)(OK)
}

// 保存商户套餐价格配置
func HandleSavePlacePriceMulti(ctx *gin.Context) {
	param := &struct {
		Price string `json:"price"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	var lists []*prices.PriceModel
	_ = json.Unmarshal([]byte(param.Price), &lists)

	//log.Println("param.Price：", param.Price)
	placeId := 0
	beforeInfo := ""
	afterInfo := ""

	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前代理商ID
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	loginUserName, err1 := helper.GetUserNameFromCtx(ctx) // 获取当前代理商ID
	if err1 != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}

	for _, lst := range lists {
		lst.ProductId = utils.Str2Md5(strconv.Itoa(lst.Id) + time.Now().Format("20060102150405") + utils.GetRandomStringAndInt(8))
		lst.Id = 0
		lst.CreateAt = dingo.Time(time.Now().Unix())
		//log.Println("价格为：", lst.PayMoney)
		placeId = lst.PlaceId
		//placeName = lst.place

		// 修改后的 免押密码线计费规则
		afterInfo = afterInfo + GetPlacePriceChangeInfo(lst, "")
	}

	// 添加日志
	// 套餐密码线计费
	priceInfo := dao.NewPricesDao().GetPlacePriceByTypeIdPre(placeId, 12, 5, 0, "create_at desc, priority asc").Unwrap().([]*prices.PriceModel)
	for _, lst := range priceInfo {
		// 修改前的 免押密码线计费规则
		beforeInfo = beforeInfo + GetPlacePriceChangeInfo(lst, "")
	}

	// 初始化模型
	priceslogModel := priceslog.New()
	priceslogModel.UserId = loginUserId
	priceslogModel.UserName = loginUserName
	priceslogModel.PlaceId = placeId
	priceslogModel.CreateAt = dingo.Time(time.Now().Unix())
	priceslogModel.PriceBefore = "修改之前，套餐密码线计费规则为 " + beforeInfo
	priceslogModel.PriceAfter = "修改之后，套餐密码线计费规则为 " + afterInfo
	priceslogModel.OperateIP = ctx.ClientIP()

	dao.NewPlacePriceLogsDao().InsertPlacePriceLogs(priceslogModel)

	Response(ctx)("修改成功", CodeSuccess, dao.NewPricesDao().SavePlaceMultiPrice(lists).Unwrap())(OK)
}

// 按天查询商户交易、订单详情
func HandelerGetOrdersStatisticsDayList(ctx *gin.Context) {
	// 请求参数处理
	param := &request.OrdersstaListReq{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	data := dao.NewOrderDao().GetOrdersStatisticsDayList(param)
	lists := data.Unwrap().([]*ordersstatistics.OrdersstatisticsModel)
	//// 设备数
	//deviceCount := dao.NewPlaceDao().GetPlaceById(param.PlaceId).Unwrap().(*placemodel.PlaceModel).DeviceCount
	var BeijingLocation = time.FixedZone("Asia/Shanghai", 8*60*60)
	for _, lst := range lists {
		// 设备数
		lst.DeviceCount = lst.DeviceTotal
		stamp, _ := time.ParseInLocation("2006-01-02", lst.IncomeDay, BeijingLocation)
		lst.CreateAt = dingo.Time(stamp.Unix())
		// 将 ettlementMoneys 由分转为元
		//ettlementMoneysYun := decimal.NewFromInt(lst.SettlementMoney).Div(decimal.NewFromInt(100)).String()
		// 客单价 单位：元 = 订单总金额/订单数
		//var ordersCountMoney = decimal.NewFromInt(lst.SettlementMoney)
		//ordersCountMoney.Div(decimal.NewFromInt(lst.OrderCount))
		if lst.SettlementMoney == 0 || lst.OrderCount == 0 {
			lst.Arpa = "0.00"
		} else {
			lst.Arpa = decimal.NewFromInt(lst.SettlementMoney).Div(decimal.NewFromInt(100)).Div(decimal.NewFromInt(lst.OrderCount)).Truncate(2).String()
		}

		// 使用率 = 定单数/设备总数
		if lst.DeviceCount > 0 {
			lst.UsageRate = decimal.NewFromInt(lst.OrderCount).Div(decimal.NewFromInt(int64(lst.DeviceCount))).Truncate(2).String()
		} else {
			lst.UsageRate = "0"
		}

	}
	// 分页信息
	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  0,
		Data:       lists,
	})(OK)
}

// 按月查询商户交易、订单详情
func HandelerGetOrdersStatisticsMonthList(ctx *gin.Context) {
	// 请求参数处理
	param := &request.OrdersstaListReq{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	data := dao.NewOrderDao().GetOrdersStatisticsMonthList(param)
	lists := data.Unwrap().([]*ordersstatistics.OrdersstatisticsModel)
	// 设备数
	deviceCount := dao.NewPlaceDao().GetPlaceById(param.PlaceId).Unwrap().(*placemodel.PlaceModel).DeviceCount

	for _, lst := range lists {
		// 设备数
		lst.DeviceCount = deviceCount
		// 将 ettlementMoneys 由分转为元
		//ettlementMoneysYun := decimal.NewFromInt(lst.SettlementMoney).Div(decimal.NewFromInt(100)).String()
		// 客单价 单位：元 = 订单总金额/订单数
		lst.Arpa = decimal.NewFromInt(lst.SettlementMoney).Div(decimal.NewFromInt(100)).Div(decimal.NewFromInt(lst.OrderCount)).Truncate(4).String()
		// 使用率 = 定单数/设备总数
		if lst.DeviceCount > 0 {
			lst.UsageRate = decimal.NewFromInt(lst.OrderCount).Div(decimal.NewFromInt(int64(lst.DeviceCount))).Truncate(2).String()
		} else {
			lst.UsageRate = "0"
		}
	}

	Response(ctx)("", CodeSuccess, lists)(OK)
}

// 回本周期计算
func HandelerGetPlaceRecovery(ctx *gin.Context) {
	// 请求参数处理
	param := &request.OrdersstaListReq{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()
	// 该商户所有收益总合，单位是：分
	placeAllIncome := dao.NewOrderDao().GetPlaceAllIncome(param.PlaceId, "").Unwrap().(int64)
	// 商户
	placeInfo := dao.NewPlaceDao().GetPlaceById(param.PlaceId).Unwrap().(*placemodel.PlaceModel)
	// 商户创建时间
	placeCreateAt := placeInfo.CreateAt
	// 商户创建时间与现在时间相关多少天
	t := time.Now().Sub(time.Unix(int64(placeCreateAt), 0)).Hours() / 24
	// 投放天数 精确1位小数点
	timeDay := decimal.NewFromFloat(t).Truncate(1)
	// 总收益 分转元
	placeAllIncomeYun := decimal.NewFromInt(placeAllIncome).Div(decimal.NewFromInt(100))
	// 天收益 = 累计收益/投放天数 单位：元
	palceAvgDayIncome := placeAllIncomeYun.Div(timeDay)
	// 商户成本 = 设备数*成本价，暂时充电线定为13元/条
	placeCost := placeInfo.DeviceCount * 13
	// 回本天数 = 成本/天收益
	//dayRecovery := decimal.NewFromInt(int64(placeCost)).Div(palceAvgDayIncome)
	var dayRecovery decimal.Decimal
	if palceAvgDayIncome.Sign() == 0 {
		dayRecovery = decimal.NewFromInt(0)
	} else {
		dayRecovery = decimal.NewFromInt(int64(placeCost)).Div(palceAvgDayIncome)
	}
	// 回本周期 = 回本天数/30
	monthRecovery := dayRecovery.Div(decimal.NewFromInt(30))
	// 剩余回本周期 = 回本周期 - 已回本周期(天收益*投放天数)
	otherMonthRecovery := monthRecovery.Sub(palceAvgDayIncome.Mul(timeDay))

	info := ordersstatistics.New()
	// 投入成本 单位：元
	info.PlaceCost = placeCost
	// 投放天数
	info.TimeDay = timeDay.String()
	// 累计收益 单位：分
	info.Income = placeAllIncome
	// 回本周期
	info.MonthRecovery = monthRecovery.String()
	// 剩余回本周期
	info.OtherMonthRecovery = otherMonthRecovery.String()

	Response(ctx)("", CodeSuccess, info)(OK)
}

// 获取网点等级
func HandleGetPlaceLevelCount(ctx *gin.Context) {
	loginUserId, err := helper.GetUserIdFromCtx(ctx)
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	isAdmin, _ := helper.GetIsAdminFromCtx(ctx)
	isPlace, _ := helper.GetIsPlaceFromCtx(ctx)

	Response(ctx)(
		"",
		CodeSuccess,
		&struct {
			SCount int64 `json:"s_count"`
			ACount int64 `json:"a_count"`
			BCount int64 `json:"b_count"`
			CCount int64 `json:"c_count"`
			DCount int64 `json:"d_count"`
			ECount int64 `json:"e_count"`
		}{
			SCount: dao.NewUserDao().GetPlaceLevelCount("S", loginUserId, isAdmin, isPlace).Unwrap().(int64),
			ACount: dao.NewUserDao().GetPlaceLevelCount("A", loginUserId, isAdmin, isPlace).Unwrap().(int64),
			BCount: dao.NewUserDao().GetPlaceLevelCount("B", loginUserId, isAdmin, isPlace).Unwrap().(int64),
			CCount: dao.NewUserDao().GetPlaceLevelCount("C", loginUserId, isAdmin, isPlace).Unwrap().(int64),
			DCount: dao.NewUserDao().GetPlaceLevelCount("D", loginUserId, isAdmin, isPlace).Unwrap().(int64),
			ECount: dao.NewUserDao().GetPlaceLevelCount("E", loginUserId, isAdmin, isPlace).Unwrap().(int64),
		},
	)(OK)
}

// 导出网点
func HandleExportPlace(ctx *gin.Context) {
	// 请求参数处理
	param := &request.UserList{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()
	//param.IsAdmin = 3
	//param.IsPlace = 1

	// 查询结果
	data := dao.NewUserDao().GetPlaceUserList(param)
	// 分页信息
	Response(ctx)("", CodeSuccess, data.Unwrap())(OK)
}

// 网点评分 日志表
func HandleGetPlaceLevelLogList(ctx *gin.Context) {
	// 请求参数处理
	param := &request.PlacesLevelListReq{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前代理商ID
	isAdmin, err := helper.GetIsAdminFromCtx(ctx)
	parentId, err := helper.GetParentIdFromCtx(ctx)
	dingo.ErrorIf(err).Unwrap()
	if isAdmin == helper.TypeNumIsAdminAdministrator || (isAdmin == helper.TypeNumIsAdminStaff && parentId == 2) {
		loginUserId = 2
	}

	data := dao.NewPlaceDao().GetPlaceLevelLogList(param, loginUserId)
	lists := data.Unwrap().([]*placemodel.PlaceLevelLogModel)

	// 分页信息
	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       lists,
	})(OK)
}

// 手动评级
func HandleAddPlaceLevel(ctx *gin.Context) {
	logic.NewTaskLogic().UpdatePlaceLevel()
	Response(ctx)("", CodeSuccess, true)(OK)
}

// 测试用
func HandlePlaceLevelAll(ctx *gin.Context) {
	for i := 120; i >= 1; i-- {
		logic.NewTaskLogic().UpdatePlaceLevelTest(30+i, i)
	}
	Response(ctx)("", CodeSuccess, true)(OK)
}

// 获取商户分润详情
func HandleGetPlaceProfit(ctx *gin.Context) {
	param := &struct {
		PlaceId int `form:"id"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	userList := make([]*users.UserModel, 0)

	if param.PlaceId > 0 {
		userInfo := dao.NewUserDao().GetUserInfoByPlaceId(param.PlaceId).Unwrap().(*users.UserModel)
		userInfo.RealProfit = userInfo.ProfitProportion
		userList = append(userList, userInfo)

		if branchUserInfo := dao.NewUserDao().GetBranchUserInfoByPlaceId(param.PlaceId).Unwrap().(*users.UserModel); branchUserInfo.ID > 0 {
			userList = append(userList, branchUserInfo)
		}
		//for _,lst := range lists {
		//	log.Println(lst)
		//}
		// 排序
		//sort.Slice(lists, func(i, j int) bool {
		//	if lists[i].ProfitProportion != lists[j].ProfitProportion {
		//		return lists[i].ProfitProportion > lists[j].ProfitProportion
		//	}
		//	return lists[i].ProfitProportion > lists[j].ProfitProportion
		//})
		sort.Slice(userList, func(i, j int) bool {
			if userList[i].ProfitProportion != userList[j].ProfitProportion {
				return userList[i].ProfitProportion < userList[j].ProfitProportion
			}
			if userList[i].IsAdmin != userList[j].IsAdmin {
				return userList[i].IsAdmin > userList[j].IsAdmin
			}

			IsPlaces := "1230"
			iIndex := strings.Index(IsPlaces, fmt.Sprintf("%d", userList[i].IsPlace))
			jIndex := strings.Index(IsPlaces, fmt.Sprintf("%d", userList[j].IsPlace))
			return iIndex < jIndex
			//return userList[i].IsPlace < userList[j].IsPlace
		})

	}

	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     1,
		PageSize:   10,
		TotalCount: 0,
		TotalPage:  0,
		Data:       userList,
	})(OK)

}

// 获取已达标商户
func HandleGetPlaceEntryList(ctx *gin.Context) {
	userId, err := helper.GetUserIdFromCtx(ctx) // 获取当前代理商ID
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	isAdmin, err := helper.GetIsAdminFromCtx(ctx) // 从上下文中获取用户是否为管理员
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}

	// 请求参数处理
	param := &request.BaseListReq{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	agentUserId := dao.GetAgentUserId(isAdmin, userId)

	data := dao.NewUserDao().GetPlaceEntryList(param, agentUserId)
	lists := data.Unwrap().([]placeresp.PlaceInfoWithEntry)
	for _, lst := range lists {
		lst.Total = dao.NewOrderDao().GetUserIncomeBeginTime(lst.Id, int64(lst.EntryAt)).Unwrap().(int64)
	}

	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       data.Unwrap(),
	})(OK)
}

//
func HandleGetPlaceByName(ctx *gin.Context) {
	// 请求参数处理
	param := &struct {
		PlaceName string `form:"placeName"`
		PlaceId   int    `form:"placeId"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	// 分页信息
	Response(ctx)(
		"",
		CodeSuccess,
		dao.NewPlaceDao().GetPlaceByName(param.PlaceName, param.PlaceId).Unwrap(),
	)(OK)
}

//获取网点信息
func HandleGetPlaceNameList(c *gin.Context) {
	param := &struct {
		PlaceName   string `json:"placeName" form:"placeName" `
		BaseListReq request.BaseListReq
	}{}
	dingo.ErrorIf(c.Bind(param)).Unwrap()
	if param.PlaceName == "" {
		param.BaseListReq.PageSize = 10
		param.BaseListReq.PageNo = 1
	}
	data := dao.NewPricesDao().GetPlaceNameList(param.PlaceName, &param.BaseListReq)
	Response(c)("", CodeSuccess, data.Unwrap())(OK)
}

//网点导入设备
func HandleImportDevice(c *gin.Context) {
	param := &struct {
		PlaceId      int      `json:"placeId" `
		PlaceName    string   `json:"placeName"`
		DevicesSnArr []string `json:"devicesSnArr"`
	}{}
	dingo.ErrorIf(c.Bind(param)).Unwrap()

	var updateQuery = []interface{}{param.DevicesSnArr}
	updMap := map[string]interface{}{
		"place_id":   param.PlaceId,
		"place_name": param.PlaceName,
		"state":      2,
		"update_at":  dingo.Time(time.Now().Unix()),
	}

	//查出已绑定的线
	devicesArr := dao.NewPricesDao().GetPlaceDevice(param.DevicesSnArr).Unwrap().([]string)

	updateState := dao.NewPricesDao().PlacePinDingDevice(&updateQuery, updMap).Unwrap().(bool)
	if !updateState {
		Response(c)("导入失败", CodeError, updateState)(OK)
	}
	if len(devicesArr) > 0 && updateState {
		Response(c)("导入成功,存在导入失败的设备线", CodeError, devicesArr)(OK)
		return
	}

	Response(c)("导入成功", CodeSuccess, updateState)(OK)
}

func GetPlaceListNoPager(ctx *gin.Context) {
	// 请求参数处理
	param := &struct {
		PlaceName string `form:"placeName"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()
	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前代理商ID
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	isAdmin, err := helper.GetIsAdminFromCtx(ctx) // 从上下文中获取用户是否为管理员
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}

	// 分页信息
	Response(ctx)("",
		CodeSuccess,
		dao.NewPlaceDao().GetPlaceListNoPager(param.PlaceName, loginUserId, isAdmin).Unwrap())(OK)
}

// 查询网点物流
func GetPlaceLogisticsInfo(ctx *gin.Context) {
	param := &placemodel.PlaceLogisticsModel{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	Response(ctx)("",
		CodeSuccess,
		dao.NewLogisticsDao().GetPlaceLogisticsInfo(param).Unwrap())(OK)
}

// 新增网点物流
func InsertPlaceLogistics(ctx *gin.Context) {
	param := &placemodel.PlaceLogisticsModel{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	Response(ctx)("",
		CodeSuccess,
		dao.NewLogisticsDao().InsertPlaceLogisticsInfo(param).Unwrap())(OK)
}

// 批量新增网点物流
func BatchInsertPlaceLogistics(ctx *gin.Context) {
	var param []*placemodel.PlaceLogisticsModel
	dingo.ErrorIf(ctx.ShouldBindJSON(&param)).Unwrap()

	Response(ctx)("",
		CodeSuccess,
		dao.NewLogisticsDao().BatchInsertPlaceLogisticsInfo(param).Unwrap())(OK)
}

// 批量新增网点物流-酒店ID
func BatchInsertPlaceLogisticsHotel(ctx *gin.Context) {
	var param []*places.PlaceInsertLogisticsModel
	dingo.ErrorIf(ctx.ShouldBindJSON(&param)).Unwrap()

	var errList []string
	var hotelIds []string
	var placeIds []int
	var insertParam []*placemodel.PlaceLogisticsModel
	for _, item := range param {
		if item.HotelId != "" {
			hotelIds = append(hotelIds, item.HotelId)
		}
		if item.PlaceId > 0 {
			placeIds = append(placeIds, item.PlaceId)
		}
	}
	placeList := dao.NewLogisticsDao().GetPlaceIdsInHotel(hotelIds, placeIds).Unwrap().([]*placemodel.PlaceModel)
	for _, item := range param {
		errOff := true
		for _, item1 := range placeList {
			if item.PlaceId == item1.Id || (item.HotelId == item1.HotelId && item.HotelId != "") {
				insertParam = append(insertParam, &placemodel.PlaceLogisticsModel{
					PlaceId:          item1.Id,
					MailPhone:        item.MailPhone,
					ReceivePhone:     item.ReceivePhone,
					LogisticsOrderNo: item.LogisticsOrderNo,
				})
				errOff = false
				break
			}
		}

		if errOff {
			errList = append(errList, item.LogisticsOrderNo)
		}
	}

	Response(ctx)("",
		CodeSuccess,
		map[string]interface{}{
			"isSuccess": dao.NewLogisticsDao().BatchInsertPlaceLogisticsInfo(insertParam).Unwrap(),
			"errList":   errList,
		})(OK)
}

// 修改网点物流
func UpdatePlaceLogistics(ctx *gin.Context) {
	param := &placemodel.PlaceLogisticsModel{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	Response(ctx)("",
		CodeSuccess,
		dao.NewLogisticsDao().UpdatePlaceLogisticsInfo(param).Unwrap())(OK)
}

// 删除网点物流
func DeletePlaceLogistics(ctx *gin.Context) {
	param := &placemodel.PlaceLogisticsModel{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	Response(ctx)("", CodeSuccess, dao.NewLogisticsDao().DeletePlaceLogistics(param).Unwrap())(OK)
}

// 查询网点物流
func GetPlaceLogisticsList(ctx *gin.Context) {
	loginUserId, err := helper.GetUserIdFromCtx(ctx)
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	isAdmin, _ := helper.GetIsAdminFromCtx(ctx)
	parentId, _ := helper.GetParentIdFromCtx(ctx)

	// 超级管理员 && 运营商下的员工
	if isAdmin == helper.TypeNumIsAdminAdministrator || (isAdmin == helper.TypeNumIsAdminStaff && parentId == 2) {
		loginUserId = 2
	}

	param := &request.PlaceLogisticsModelListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	param.LoginUserId = loginUserId
	param.IsAdmin = isAdmin

	data := dao.NewLogisticsDao().GetPlaceLogisticsList(param)
	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       data.Unwrap(),
	})(OK)
}

//查询撤回门店列表
func GetLogisticsReturnList(c *gin.Context) {
	loginUserId, err := helper.GetUserIdFromCtx(c)
	if err != nil {
		Response(c)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	isAdmin, _ := helper.GetIsAdminFromCtx(c)

	param := &request.PlaceLogisticsModelListReq{}
	dingo.ErrorIf(c.ShouldBindJSON(param)).Unwrap()
	param.LoginUserId = loginUserId
	param.IsAdmin = isAdmin

	data := dao.NewLogisticsDao().GetLogisticsReturnList(param)
	Response(c)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       data.Unwrap(),
	})(OK)
}

//更新酒店公告
func UpdatePlaceBulletin(c *gin.Context) {
	param := &placeresp.PlaceBulletin{}
	dingo.ErrorIf(c.Bind(param)).Unwrap()

	Response(c)("", CodeUpdateSuccess, dao.NewPlaceDao().UpdatePlaceAnnouncement(param).Unwrap())(OK)
}

// HandleGetPlaceRoomList 获取门店房间号列表
func HandleGetPlaceRoomList(ctx *gin.Context) {
	param := &request.GetPlaceRoomListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	data := dao.NewRoomDaoDao().GetRoomList(param)

	list := data.Unwrap().([]*request.GetDeviceRoomListRes)

	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  (data.Val().(int64) + int64(param.PageSize) - 1) / int64(param.PageSize),
		Data:       list,
	})(OK)
}

// HandleDeletePlaceRoom 删除房间号
func HandleDeletePlaceRoom(ctx *gin.Context) {
	param := &struct {
		Room    string `json:"room"`
		PlaceId int    `json:"placeId"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	isDelete := dao.NewRoomDaoDao().DeletePlaceRoom(param.Room, param.PlaceId).Unwrap().(bool)
	if isDelete {
		Response(ctx)("删除成功", CodeSuccess, true)(OK)
		return
	} else {
		Response(ctx)("删除失败", CodeError, false)(OK)
		return
	}
}

// HandleClearPlaceRoom 清空房间号
func HandleClearPlaceRoom(ctx *gin.Context) {
	param := &struct {
		PlaceId int `json:"placeId"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	isDelete := dao.NewRoomDaoDao().ClearPlaceRoom(param.PlaceId).Unwrap().(bool)
	if isDelete {
		Response(ctx)("清空成功", CodeSuccess, true)(OK)
		return
	} else {
		Response(ctx)("清空失败", CodeError, false)(OK)
		return
	}
}

// HandleUpdatePlaceRoom 修改房间号
func HandleUpdatePlaceRoom(ctx *gin.Context) {
	param := &request.SetStewardDeviceReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	c := dao.NewRoomDaoDao().SearchRoomIsBindDeviceSn(param).Unwrap().(int64)
	if c > 0 {
		Response(ctx)("该设备已绑定了房间号", CodeError, false)(OK)
		return
	}
	placeRes := dao.NewRoomDaoDao().UpdatePlaceRoom(param).Unwrap().(bool)
	devRes := dao.NewRoomDaoDao().UpdateDeviceRoom(param).Unwrap().(bool)
	if placeRes && devRes {
		Response(ctx)("修改成功", CodeSuccess, true)(OK)
		return
	}

	Response(ctx)("修改失败", CodeError, false)(OK)
}
